#include "Hash.h"
#include <assert.h>
#include <string.h>

Hash::Hash(HashType type) {
    _type = type;
    _ctx = EVP_MD_CTX_new();
    assert(_ctx != NULL);
    int ret = EVP_DigestInit_ex(_ctx, HashMethods.at(_type)(), NULL);
    assert(ret == 1);
}

Hash::~Hash() {
    if (_ctx != NULL) {
        EVP_MD_CTX_free(_ctx);
    }
}

// 添加数据
void Hash::addData(string data) {
    addData(data.data(), data.size());
}

// 添加数据
void Hash::addData(const char *data, int length) {
    int ret = EVP_DigestUpdate(_ctx, data, length);
    assert(ret == 1);
}

// 计算结果, 有2种格式: 二进制格式、16进制数字串格式
string Hash::result(Type type) {
    unsigned int len = 0;
    unsigned char md[HashLengths.at(_type)];
    int ret = EVP_DigestFinal(_ctx, md, &len); // md为二进制格式
    assert(ret == 1);
    if (type == Type::Hex) { // 将md转化为16进制数字串格式: 8个bit = 1个字符(0~256) = 2个16进制数字
        char res[len * 2];
        for (int i = 0; i < len; i++) {
            sprintf(&res[i * 2], "%02x", md[i]);
        }
        return string(res, len * 2);
    }
    return string(reinterpret_cast<char*>(md), len);
}